﻿using System.Collections.Generic;

namespace Nutilities.Collections.Monitors
{
    public class DictionaryMonitor<TKey, TValue>
    {
        public object SyncRoot { get; private set; }
        public Dictionary<TKey, TValue> Dictionary { get; set; }

        public DictionaryMonitor(Dictionary<TKey, TValue> dictionary)
        {
            Dictionary = dictionary;
            SyncRoot = new object();
        }

        // Altering operations
        public void Add(TKey key, TValue value)
        {
            lock (SyncRoot)
            {
                Dictionary = new Dictionary<TKey, TValue>(Dictionary);
                Dictionary.Add(key, value);
            }
        }

        public bool Remove(TKey key)
        {
            lock (SyncRoot)
            {
                Dictionary = new Dictionary<TKey, TValue>(Dictionary);
                return Dictionary.Remove(key);
            }
        }

        public void Clear()
        {
            lock (SyncRoot)
            {
                Dictionary = new Dictionary<TKey, TValue>();
            }
        }

        public bool ContainsKey(TKey key)
        {
            lock (SyncRoot)
            {
                return Dictionary.ContainsKey(key);
            }
        }

        public bool ContainsValue(TValue value)
        {
            lock (SyncRoot)
            {
                return Dictionary.ContainsValue(value);
            }
        }

        public bool TryGetValue(TKey key, out TValue value)
        {
            lock (SyncRoot)
            {
                return Dictionary.TryGetValue(key, out value);
            }
        }

        public TValue this[TKey key]
        {
            get
            {
                // Non-altering operation
                lock (SyncRoot)
                {
                    return Dictionary[key];
                }
            }
            set
            {
                // Altering operation
                lock (SyncRoot)
                {
                    Dictionary = new Dictionary<TKey, TValue>(Dictionary);
                    Dictionary[key] = value;
                }
            }
        }
    }
}
